package multidraw.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

public class Zip {
	static final int BUFFER = 2048;

	public static void main(String[] args) throws Exception {
		zipDirectory(new File("tools"), new File("d:\\tmp\\myfigs1.zip"));
		unzip(new File("d:\\tmp\\myfigs1.zip"), new File("d:\\tmp\\unziptest"));
		byte[] output = zipDirectoryToByteArray(new File("tools"));
		System.out.println(output.length);
		unzipFromByteArray(output, new File("d:\\tmp\\unziptest1"));
	}
	
	public static void test1() {
		try {
			BufferedInputStream origin = null;
			FileOutputStream dest = new FileOutputStream("d:\\tmp\\myfigs.zip");
			ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
					dest));
			// out.setMethod(ZipOutputStream.DEFLATED);
			byte data[] = new byte[BUFFER];
			// get a list of files from current directory
			File f = new File("tools/triangletool");
			String files[] = f.list();

			for (int i = 0; i < files.length; i++) {
				System.out.println("Adding: " + files[i]);
				FileInputStream fi = new FileInputStream(new File(f, files[i]));
				origin = new BufferedInputStream(fi, BUFFER);
				ZipEntry entry = new ZipEntry(files[i]);
				out.putNextEntry(entry);
				int count;
				while ((count = origin.read(data, 0, BUFFER)) != -1) {
					out.write(data, 0, count);
				}
				origin.close();
			}
			out.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static final void zipDirectory(File directory, File zip)
			throws IOException {
		ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip));
		zip(directory, directory, zos);
		zos.close();
	}

	private static final void zip(File directory, File base, ZipOutputStream zos)
			throws IOException {
		File[] files = directory.listFiles();
		byte[] buffer = new byte[8192];
		int read = 0;
		for (int i = 0, n = files.length; i < n; i++) {
			if (files[i].isDirectory()) {
				zip(files[i], base, zos);
			} else {
				FileInputStream in = new FileInputStream(files[i]);
				ZipEntry entry = new ZipEntry(files[i].getPath().substring(
						base.getPath().length() + 1));
				zos.putNextEntry(entry);
				while (-1 != (read = in.read(buffer))) {
					zos.write(buffer, 0, read);
				}
				in.close();
			}
		}
	}

	public static final void unzip(File zip, File extractTo) throws IOException {
		ZipFile archive = new ZipFile(zip);
		Enumeration e = archive.entries();
		while (e.hasMoreElements()) {
			ZipEntry entry = (ZipEntry) e.nextElement();
			File file = new File(extractTo, entry.getName());
			if (entry.isDirectory() && !file.exists()) {
				file.mkdirs();
			} else {
				if (!file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}

				InputStream in = archive.getInputStream(entry);
				BufferedOutputStream out = new BufferedOutputStream(
						new FileOutputStream(file));

				byte[] buffer = new byte[8192];
				int read;

				while (-1 != (read = in.read(buffer))) {
					out.write(buffer, 0, read);
				}

				in.close();
				out.close();
			}
		}
	}
	
	public static final byte[] zipDirectoryToByteArray(File directory)
			throws IOException {
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ZipOutputStream zos = new ZipOutputStream(bos);
		zip(directory, directory, zos);
		zos.close();
		return bos.toByteArray();
	}
	
	public static final void unzipFromByteArray(byte[] zip, File extractTo) throws IOException {
		ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(zip));
		// ZipFile archive = new ZipFile(zip);
		ZipEntry entry;
		// while there are entries I process them
		ZipEntry ze;
		long totalBytesRead = 0;
		
		while ((entry = zis.getNextEntry()) != null) {
			System.out.println("entry: " + entry.getName() + ", "
					+ entry.getSize());
			// consume all the data from this entry
			File file = new File(extractTo, entry.getName());
			if (entry.isDirectory() && !file.exists()) {
				file.mkdirs();
			} else {
				if (!file.getParentFile().exists()) {
					file.getParentFile().mkdirs();
				}

				BufferedOutputStream outStream = new BufferedOutputStream(
						new FileOutputStream(file));
				byte[] buffer = new byte[4096];
				int i;
				while ((i = zis.read(buffer)) != -1) {
					totalBytesRead += i;
					outStream.write(buffer, 0, i);
				}
				outStream.close();
			}
		}

	}
}
